Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement constraint merging for correctness #13292

Merged
merged 4 commits into from
Aug 18, 2021

Conversation

smarter
Copy link
Member

@smarter smarter commented Aug 13, 2021

The previous implementation simply combined the content of both
constraints into one, but this is not enough since it meant that bounds
were not propagated and so transitivity was violated. For example, when
merging a constraint containing ?S <: ?T and one containing ?T <: ?R,
the result did not verify?S <:< ?R (see the unit tests added in
ConstraintsTest).

The new implementation simply starts with one set of constraints and
then adds the constraints from the other set one by one using <:<
which takes care of propagating bounds. This is likely to be more
expensive than the previous implementation but it turns out that
TyperState#mergeConstraintWith is a rare operation (it is
only called 43 times when compiling scala3-compiler), so
the difference shouldn't be significant.

This also incidentally fixes #12730 because the previous logic for
checking if merging succeeded was flawed.

Otherwise they will keep accumulating across multiple compiler instances
since Stats is global.
When printing a constraint, we print types which might
refer to type variables defined in the constraint, but the type printer
will rely on ctx.typerState.constraint to determine if these type
variables are instantiated, and this might be a different constraint
than the one we're trying to print, leading to an incorrect output.

This commit fixes this by temporarily setting ctx.typerState.constraint
to the current constraint when printing it, this required moving the
printing logic from OrderingConstraint to PlainPrinter.

At the same time, we drop the distinction between `toText` and
`contentsToString` (the former wrapped the printed output in
"Constraint(...)" and the latter didn't, now we never do) because
preserving it would have been complicated and it didn't seem worth it.

Also fix Ordering#toString to correctly print the bounds (the logic was
there but it was dead code).
The previous implementation simply combined the content of both
constraints into one, but this is not enough since it meant that bounds
were not propagated and so transitivity was violated. For example, when
merging a constraint containing `?S <: ?T` and one containing `?T <:
?R`, the result did not verify `?S <:< ?R` (see the unit tests added in
ConstraintsTest).

The new implementation simply starts with one set of constraints and
then adds the constraints from the other set one by one using `<:<`
which takes care of propagating bounds. This is likely to be more
expensive than the previous implementation but it turns out that
`TyperState#mergeConstraintWith` is a rare operation (after the previous
commit it is only called 43 times when compiling scala3-compiler), so
the difference shouldn't be significant.

This also incidentally fixes scala#12730 because the previous logic for
checking if merging succeeded was flawed.
@smarter
Copy link
Member Author

smarter commented Aug 13, 2021

test performance please

@dottybot
Copy link
Member

performance test scheduled: 1 job(s) in queue, 0 running.

@dottybot
Copy link
Member

Performance test finished successfully:

Visit https://dotty-bench.epfl.ch/13292/ to see the changes.

Benchmarks is based on merging with master (e4b421c)

Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it is much clearer.

@odersky odersky merged commit 45ce129 into scala:master Aug 18, 2021
@odersky odersky deleted the fix-merge-constraint-3 branch August 18, 2021 14:02
@Kordyjan Kordyjan added this to the 3.1.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash depending on where in a file a certain term is referenced
4 participants